package com.food.eat.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @Author:RenPu
 * @Date: 2020/6/25 21:36
 * @Version: 1.0
 * @description:
 */
public class RedisLock {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    /**
     * 判断订单是否被抢，被抢走：true,没被抢：fasle
     *
     * @param orderId
     * @param orderId
     */

    private boolean checkOrder(int orderId) {

        System.out.println("判断订单是否被抢");
        return true;
    }


    public Object checkOrder1(int orderId, int driverId) {

        //获取订单，判断订单是否被抢
        boolean biaoShi = checkOrder(orderId);
        if (biaoShi) {
            System.out.println("订单已经被抢");
        } else {

            //业务，绑定订单和司机，改变订单状态生成虚拟号码。
            System.out.println("订单没有被抢，司机可依就行抢单");
        }
        return null;
    }


    /**
     * 使用 synchronized实现锁机制，synchronized仅仅只能锁同一个jvm的资源
     * 不支持分布式
     *
     * @param orderId
     * @param driverId
     * @return
     */
    public Object checkOrder2(int orderId, int driverId) {

        synchronized (this) {
            checkOrder1(orderId, driverId);
        }

        return null;

    }


    /**
     * 不锁具体的订单
     *
     * @param orderId
     * @param driverId
     * @return
     */
    public Object checkOrder3(int orderId, int driverId) {

        String key = "LOCK";
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "msg");
        if (!flag) {
            System.out.println("订单被别人抢了");

        }
        checkOrder1(orderId, driverId);

        return null;

    }


    /**
     * 没有删除对应的key,对不对
     *
     * @param orderId
     * @param driverId
     * @return
     */

    public Object checkOrder4(int orderId, int driverId) {

        String key = "LOCK" + orderId;
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "");
        if (!flag) {
            System.out.println("订单的司机太多了");
        }
        checkOrder1(orderId, driverId);

        return null;
    }


    /**
     * 有异常，删除不了key
     *
     * @param orderId
     * @param driverId
     * @return
     */
    public Object checkOrder5(int orderId, int driverId) {
        String key = "LOCK" + orderId;
        Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "");
        if (!flag) {
            System.out.println("订单的司机太多了");
        }
        checkOrder1(orderId, driverId);
        redisTemplate.delete(key);
        return null;

    }


    /**
     * 运维重启服务
     *
     * @param orderId
     * @param driverId
     * @return
     */
    public Object checkOrder6(int orderId, int driverId) {
        String key = "LOCK" + orderId;
        try {
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "msd");
            if (!flag) {
                System.out.println("订单的司机太多了");
                return null;
            }
            checkOrder1(orderId, driverId);
        } finally {
            redisTemplate.delete(key);
        }
        return null;

    }


    /**
     * 上锁后没有执行完过期时间怎么办
     *
     * @param orderId
     * @param driverId
     * @return
     */
    public Object checkOrder7(int orderId, int driverId) {
        String key = "LOCK" + orderId;
        try {
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "msd");
            redisTemplate.expire(key, 10, TimeUnit.SECONDS);
            if (!flag) {
                System.out.println("订单的司机太多了");
                return null;
            }
            checkOrder1(orderId, driverId);
        } finally {
            redisTemplate.delete(key);
        }
        return null;

    }


    /**
     * 前面的线程进来把当前key移除了，并且第二线程已经拿到锁了怎么处理
     *
     * @param orderId
     * @param driverId
     * @return
     */
    public Object checkOrder8(int orderId, int driverId) {
        String key = "LOCK" + orderId;
        try {
            //原子操作
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, "msd", 10, TimeUnit.SECONDS);

            if (!flag) {
                System.out.println("订单的司机太多了");
                return null;
            }
            checkOrder1(orderId, driverId);
        } finally {
            redisTemplate.delete(key);
        }
        return null;

    }


    /**
     * 万一锁自动超时了，释放了怎么办
     *
     * @param orderId
     * @param driverId
     */
    public Object checkOrder9(int orderId, int driverId) {
        String key = "LOCK" + orderId;
        String uuid = UUID.randomUUID().toString();
        try {
            //原子操作
            Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, uuid, 10, TimeUnit.SECONDS);

            if (!flag) {
                System.out.println("订单的司机太多了");
                return null;
            }
            checkOrder1(orderId, driverId);
        } finally {
            if (uuid.equals(redisTemplate.opsForValue().get(key))) {
                redisTemplate.delete(key);
            }
        }
        return null;

    }
}
